/*  This file is part of LibGChart.
 *
 * AUTHORS
 *       Sascha Dewald        <sascha.dewald@googlemail.com>
 *
 * Copyright (C) 2009 Sascha Dewald
 *
 *  
 *  
 *  LibGChart is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Foobar is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with LibGChart.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

using System;
using System.Collections;

using Cairo;

namespace LibGChart
{
	
	/**
	 * class GSeries, represent a Series of Points
	 */
	public class GSeries : System.Collections.IEnumerable
	{
		private GCaption title;
		private Color color;
		
		internal GAxis xaxis, yaxis;
		
		private ArrayList pointList;
		
		/**
		 * Property Title, represent the title of the Series, shown in the Legend
		 */
		public GCaption Title
		{
			get { return title; }
		}
		
		/**
		 * default constructor
		 */
		public GSeries(string title)
		{
			color = new Color(1.0, 0.0, 0.0);
			
			// Allocate a array List with a starting Capacity for 128 points
			pointList = new ArrayList(128);
			
			this.title = new GCaption();
			this.title.Text = title;
		}
		
		/** 
		 * Add a new Point
		 */
		public void Add(GPoint point)
		{
			pointList.Add(point);
			
			if ((xaxis != null) && (yaxis != null))
			{
				point.realX = xaxis.calc_coord_value(point.ValueX);
				point.realY = yaxis.calc_coord_value(point.ValueY);
			}
		}
		
		/** 
		 * Remove a new Point
		 */
		public void Remove(GPoint point)
		{
			pointList.Remove(point);
		}
		
		/**
		 * Get the count of points
		 */
		public int Count
		{
			get { return pointList.Count; }
		}
		
		/** 
		 * Get/set element at given index
		 */
		public GPoint this[int index]
		{
			get { return (GPoint)pointList[index]; } //FIXME: should i better use "as"
			set { pointList[index] = value; }
		}
		
		/** 
		 * Get/set element at given index
		 */
		public IEnumerator GetEnumerator()
		{
			return pointList.GetEnumerator();
		}
		
		/**
		 * function calc_real_coords, calculate the real coords of the Points inside the series
		 */
		internal void calc_real_coords_xy()
		{
			IEnumerator pointsEnumerator = GetEnumerator(); 
			
			pointsEnumerator.Reset(); // FIXME: properly not needed
			
			while ( pointsEnumerator.MoveNext()) 
			{
				GPoint point = (pointsEnumerator.Current as GPoint);
				point.realX = xaxis.calc_coord_value(point.ValueX);
				point.realY = yaxis.calc_coord_value(point.ValueY);
			}
		}
		
		/**
		 * function calc_real_coords, calculate the real coords of the Points inside the series
		 */
		internal void calc_real_coords_x()
		{
			IEnumerator pointsEnumerator = GetEnumerator(); 
			
			pointsEnumerator.Reset(); // FIXME: properly not needed
			
			while ( pointsEnumerator.MoveNext()) 
			{
				GPoint point = (pointsEnumerator.Current as GPoint);
				point.realX = xaxis.calc_coord_value(point.ValueX);
			}
		}
		
		/**
		 * function calc_real_coords, calculate the real coords of the Points inside the series
		 */
		internal void calc_real_coords_y()
		{
			IEnumerator pointsEnumerator = GetEnumerator(); 
			
			pointsEnumerator.Reset(); // FIXME: properly not needed
			
			while ( pointsEnumerator.MoveNext()) 
			{
				GPoint point = (pointsEnumerator.Current as GPoint);
				point.realY = yaxis.calc_coord_value(point.ValueY);
			}
		}
		
		/**
		 * public function set_color, change the color of the series
		 */
		public void set_color(double r, double g, double b)
		{
			color = new Color(r, g, b);
		}
		
		/**
		 * internal function draw, draws the series, and them points
		 */
		internal void draw(Cairo.Context cr)
		{
			IEnumerator pointsEnumerator = GetEnumerator(); 
			
			pointsEnumerator.Reset(); // FIXME: properly not needed
			
			// Init cairo
			cr.Save();
			
			cr.Color = color;
			cr.LineWidth = 2;
			cr.LineCap = LineCap.Round;
			
			// Get First Point and move to...
			pointsEnumerator.MoveNext();
			
			// Move Cairo to the First Point
			cr.MoveTo((pointsEnumerator.Current as GPoint).realX, (pointsEnumerator.Current as GPoint).realY);
			
			while ( pointsEnumerator.MoveNext()) 
			{
				//System.Console.WriteLine("...");
				
				// Draw Line to the next Point...
				cr.LineTo((pointsEnumerator.Current as GPoint).realX, (pointsEnumerator.Current as GPoint).realY);
			} 

			// Draw the Line
			cr.Stroke();
			
			// Restore Cairo to previous state
			cr.Restore();
		}
	}
}
